//
//  BHCycleView.swift
//  BigHealth
//
//  Created by 蔺百好 on 2021/7/27.
//

import UIKit
public protocol BHCycleViewDataSource: NSObjectProtocol {
    func numberOfItem(_ cycleView: UIView) -> Int
    func cellForRow(_ indexPath: IndexPath, _ collectionView: UICollectionView, _ cycleView: UIView) -> UICollectionViewCell
    func sizeForItem(_ indexPath: IndexPath,_ cycleView: UIView) -> CGSize
}

@objc protocol  BHCycleViewDelegate: NSObjectProtocol {
    @objc optional func didSelectItem(_ index: Int,_ cycleView: UIView)
}


class BHCycleView: UIView {
    enum DPScrollDirection: Int {
        case vertical = 0

        case horizontal = 1
    }
    
    
    var dataSource:  BHCycleViewDataSource?
    var delegate: BHCycleViewDelegate?
    private var timer: Timer?
    
    private var currentPage: NSInteger = 0
    private var maxCount: NSInteger = 0
    var canScroll: Bool = true {
        willSet {}
        didSet {
            self.collectionView.isScrollEnabled = canScroll
        }
    }
    
    
    fileprivate lazy var flowLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout.init()
        layout.minimumLineSpacing = 0
        return layout
    }()
    
    lazy var collectionView: UICollectionView = {
    let view = UICollectionView.buildCollectionView(layout: self.flowLayout)
        view.bounces = false
        view.isPagingEnabled = true
        view.delegate = self
        view.dataSource = self
        view.showsVerticalScrollIndicator = false
        view.showsHorizontalScrollIndicator = false
        view.backgroundColor = .clear
        view.scrollsToTop = false
        view.register(BHCommonBannerImageCell.self, forCellWithReuseIdentifier: "BHCommonBannerImageCell")
        return view
    }()
    
    var scrollDirection: DPScrollDirection! {
        willSet {}
        didSet {
            if scrollDirection == .vertical {
                self.flowLayout.scrollDirection = .vertical
            }else {
                self.flowLayout.scrollDirection = .horizontal
            }
        }
    }
    
    var leadingAndTralingSpace: CGFloat = 10 {
        willSet {}
        didSet {
            self.flowLayout.sectionInset = UIEdgeInsets(top: 0, left: leadingAndTralingSpace, bottom: 0, right: leadingAndTralingSpace)
        }
    }
    
    
    var lineSpace: CGFloat = 5 {
        willSet {}
        didSet {
            self.flowLayout.minimumLineSpacing = lineSpace
        }
    }
    
    
    func registerNib(nib: UINib, identify: String) {
        self.collectionView.register(nib, forCellWithReuseIdentifier: identify)
    }
    
    func registerClass<T: UICollectionViewCell>(cellClass: T.Type, identify: String)  {
        self.collectionView.register(cellClass, forCellWithReuseIdentifier: identify)
    }
    
    var sourceArray: [Any]! {
        willSet {}
        didSet {
            if self.timer != nil {
                self.timer!.invalidate()
                timer = nil
            }
            
            if sourceArray.count == 1 {
                self.collectionView.isScrollEnabled = false
            }else {
                if self.timerValue != 0 {
                    self.timer = Timer.scheduledTimer(timeInterval: TimeInterval(self.timerValue), target: self, selector: #selector(timerCountGo), userInfo: nil, repeats: true)
                    RunLoop.current.add(self.timer!, forMode: .common)
                }
                
                self.collectionView.isScrollEnabled = self.canScroll
            }
            self.collectionView.reloadData()
        }
    }
    
    /**
     需要在sourceArray之前赋值
     */
    var timerValue: CGFloat = 3
    
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.addSubview(self.collectionView)

    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        self.collectionView.frame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
    }
    
    
    @objc func timerCountGo() {
        if self.currentPage == self.maxCount-1 {
            if self.scrollDirection ==  .vertical{
                self.collectionView.scrollToItem(at: IndexPath.init(row: 0, section: 0), at: .centeredVertically, animated: false)
            }else {
                self.collectionView.scrollToItem(at: IndexPath.init(row: 0, section: 0), at: .centeredHorizontally, animated: false)
            }
            self.currentPage = 0
        }else {
            self.currentPage += 1
            if self.scrollDirection ==  .vertical{
                self.collectionView.scrollToItem(at: IndexPath.init(row: self.currentPage, section: 0), at: .centeredVertically, animated: true)
            }else {
                self.collectionView.scrollToItem(at: IndexPath.init(row: self.currentPage, section: 0), at: .centeredHorizontally, animated: true)
            }
        }
    }

}
extension BHCycleView {
    func realNumberOfItem() -> Int {
        let count = self.dataSource?.numberOfItem(self) ?? 0
        if count != 0 {
            if count == 1 {
                self.maxCount = 1
            }else {
                self.maxCount = count*50
            }
        }
        return self.maxCount
    }
}
extension BHCycleView {
    final func register<T: UICollectionViewCell>(classCellType: T.Type) {
        let cellID = String(describing: classCellType)
        self.collectionView.register(classCellType, forCellWithReuseIdentifier: cellID)
    }
    final func register<T: UICollectionViewCell>(nibCellType: T.Type) {
        let cellID = String(describing: nibCellType)
        let nib = UINib.init(nibName: cellID, bundle: nil)
        self.collectionView.register(nib, forCellWithReuseIdentifier: cellID)
    }
    final func dequeueReusableCell<T: UICollectionViewCell>(for indexPath: IndexPath, cellType: T.Type = T.self) -> T {
        let cellID = String(describing: cellType)
        let bareCell = self.collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath)
        guard let cell = bareCell as? T else {
            fatalError(
                "Failed to dequeue a cell with identifier \(cellID) matching type \(cellType.self). "
                    + "Check that the reuseIdentifier is set properly in your XIB/Storyboard "
                    + "and that you registered the cell beforehand"
            )
        }
        return cell
    }
}

extension BHCycleView : UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout{
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.realNumberOfItem()
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size = self.dataSource?.sizeForItem(indexPath,self) ?? .zero
        return size

    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = self.dataSource?.cellForRow(indexPath, collectionView,self) ?? UICollectionViewCell()
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let result = self.delegate?.responds(to: #selector(self.delegate?.didSelectItem(_:_:)))
        if result != nil {
            self.delegate?.didSelectItem?(indexPath.item%self.sourceArray.count,self)
        }
    }
    
}

extension BHCycleView: UIScrollViewDelegate {
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        self.timer?.pause()
    }
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        
    }
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        
    }
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let array = self.collectionView.indexPathsForVisibleItems
        let indexPath = array.last
        self.currentPage = indexPath!.row
        
        self.timer?.start(TimeInterval(self.timerValue))

    }
}
